#include <stdio.h>
#include <string.h>
#include "alfa.h"
#include "strutils.h"

void load_list(char *name,char *list[],int maxn) {
  FILE *f;
  int n;
  char s[MAXLEN];
  char *p;

  f=fopen(name,"r");
  if (f==NULL) return;
  n=0;
  while (fgets(s,sizeof(s)-1,f) && n<maxn-1) {
    p=strchr(s,'\n');
    if (p) *p=0;
    p=strchr(s,'\r');
    if (p) *p=0;
    if (s[0]==0) continue;
    list[n++]=strdup(s);
  }
  fclose(f);
  list[n]=NULL;
} //load_list

void load_list2(char *name,char *list[],int maxn) {
  FILE *f;
  int n;
  char s[MAXLEN];
  char *p;

  f=fopen(name,"r");
  if (f==NULL) return;
  n=0;
  while (fgets(s,sizeof(s)-1,f) && n<maxn-1) {
    p=strchr(s,'\n');
    if (p) *p=0;
    p=strchr(s,'\r');
    if (p) *p=0;
    if (s[0]==0) continue;
    list[n++]=strdup(s);
  }
  fclose(f);
  list[n]=NULL;
} //load_list


alfacoll Alfa1,Alfa2,CAlfa,Srg1,Srg2,Subst;

int FindColl (char *s, alfacoll *alfa) {
  int L,H,I,C;

  L=0; H=alfa->len-1;
  while (L<=H) {
    I=(L+H)/2;
    C=strcmp(alfa->coll[I].str,s);
    if (C<0)
      L=I+1;
    else {
      H=I-1;
      if (C==0)
        L=I;
    }
  }
  return L;
} //FindColl

void AddColl (alfacoll *alfa, char *str, char *key, char *low) {
  int n,i;

  if (*key==0) return;
  if (*str==0) return;
  n=FindColl(str,alfa);
  if ((alfa->coll[n].str) && (strcmp(str,alfa->coll[n].str)==0)) return;
  if (alfa->len>=COLLEN-1) return;

  for (i=alfa->len; i>=n; i--)
    alfa->coll[i]=alfa->coll[i-1];
  alfa->coll[n].str=strdup(str);
  alfa->coll[n].key=strdup(key);
  alfa->coll[n].low=strdup(low);
  alfa->len++;
} //AddColl

void ClearColl (alfacoll alfa[]) {
  int i;

  for (i=0; i<alfa->len; i++) {
    free(alfa->coll[i].str); alfa->coll[i].str=NULL;
    free(alfa->coll[i].low); alfa->coll[i].low=NULL;
    free(alfa->coll[i].key); alfa->coll[i].key=NULL;
  }
  alfa->len=0;
} //ClearColl

void LoadColl (char *name, alfacoll *alfa) {
  FILE *f;
  char s[256];
  char str[256], key[256], low[256];
  char *p,*pp;
  int i,n;

  f=fopen(name,"r");
  if (f==NULL) return;

  n=0;
  while (fgets(s,sizeof(s)-1,f) && n<255) {
    p=strchr(s,'\n');
    if (p) *p=0;
    p=strchr(s,'\r');
    if (p) *p=0;

    i=0;
    p=s;
    pp=p;

    while (*pp && *pp!=' ') pp++;
    if (*pp==0) continue;
    *pp++=0;
    while (*pp==' ') pp++;
    strcpy(key,p);
    p=pp;

    while (*pp && *pp!=' ') pp++;
    if (*pp) {
      *pp++=0;
      while (*pp==' ') pp++;
    }
    strcpy(str,p);
    p=pp;

    while (*pp && *pp!=' ') pp++;
    if (*pp) {
      *pp++=0;
      while (*pp==' ') pp++;
    }
    strcpy(low,p);
    p=pp;

    AddColl(alfa,str,key,low);

    strcpy(str,low);
    AddColl(alfa,str,key,low);

    while (*p) {
      while (*pp && *pp!=' ') pp++;
      if (*pp==0) break;
      *pp++=0;
      while (*pp==' ') pp++;
      strcpy(str,p);
      p=pp;
      AddColl(alfa,str,key,low);
    }
  }
  fclose(f);
} //LoadColl

void joinAlfa (alfacoll *alfa1, alfacoll *alfa2, alfacoll *alfa) {
  int i;
  for (i=0; i<alfa1->len; i++)
    AddColl(alfa,alfa1->coll[i].str,alfa1->coll[i].key,alfa1->coll[i].low);
  for (i=0; i<alfa2->len; i++)
    AddColl(alfa,alfa2->coll[i].str,alfa2->coll[i].key,alfa2->coll[i].low);
} //join_alfa

int Find (char *s, alfacoll *alfa) {
  int n;

  n=FindColl(s,alfa);
  while (n>=0) {
    if (alfa->coll[n].str && alfa->coll[n].str[0]) {
      if (alfa->coll[n].str[0]<s[0]) break;
      if (strncmp(s,alfa->coll[n].str,strlen(alfa->coll[n].str))==0)
        return n;
    }
    n--;
  }
  return -1;
} //Find

char *toNKey (char *s, alfacoll *alfa, int num, char *key, char *out) {
  int n, len;
  char *p;
  char buf[80];

  if (out) out[0]=0;
  if (key) key[0]=0;
  for (p=s; *p && num; p++, num--) {
    n=Find(p,alfa);
    if (n>=0) {
      if (key) strcat(key,alfa->coll[n].key);
      len=strlen(alfa->coll[n].str);
      strncpy(buf,p,len);
      buf[len]=0;
      if (out) strcat(out,buf);
      p+=len-1;
    }
    else if (*p==' ') {
      if (out) strcat(out," ");
      if (key) strcat(key,"_");
    }
    else {
      sprintf(buf,"%c",*p);
      if (out) strcat(out,buf);
      if (key) strcat(key,buf);
    }
  } //if
  return p;
} //toNKey

void toKey (char *s, alfacoll *alfa, char *key) {
  toNKey(s,alfa,-1,key,NULL);
} //toKey

int isInAlfa (char *s, alfacoll *alfa) {
  if (Find(s,alfa)<0) return 0;
  return 1;
} //isInAlfa

void to_Lower (char *s, alfacoll *alfa) {
  char buf[80], out[MAXLEN];
  int n, len;
  char *p;

  out[0]=0;
  for (p=s; *p; p++) {
    n=Find(p,alfa);
    if (n>=0) {
      len=strlen(alfa->coll[n].str);
      if (alfa->coll[n].low && alfa->coll[n].low[0])
        sprintf(buf,"%s",alfa->coll[n].low);
      else
        sprintf(buf,"%c",*p);
      strcat(out,buf);
      p+=len-1;
    }
    else {
      sprintf(buf,"%c",*p);
      strcat(out,buf);
    }
  } //if
  strcpy(s,out);
} //to_Lower
